using System.Collections.Generic;
using System.Drawing;
using System.Threading.Tasks;
using TMPro;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using Color = UnityEngine.Color;
namespace MeEditor
{
    enum PrefabCheckState
    {
        None,
        CheckingPrefab,
        CheckingPrefabEnd,
        CheckingAniamtion,
        CheckingAniamtionEnd,
        CheckingContentSizeFitter,
        CheckingContentSizeFitterEnd
    }
    public class PrefabDependencyChecker : EditorWindow
    {
        private string folderPath = "Assets/Res/Prefabs";
        private readonly List<PrefabMissingInfo> _prefabsWithMissingReferences = new List<PrefabMissingInfo>();
        private List<PrefabAnimationInfo> _prefabAutoAnimationList = new List<PrefabAnimationInfo>();
        private List<PrefabTMPInfo> _prefabTMPList = new List<PrefabTMPInfo>();
        private int totalPrefabsChecked = 0;
        private Vector2 scrollPosition;
        private PrefabCheckState _state = PrefabCheckState.None;

        private struct MissingComponentInfo
        {
            public readonly string ComponentName;
            public readonly string MissingType; 
            public readonly string MissingDetail;

            public MissingComponentInfo(string componentName, string missingType, string missingDetail)
            {
                ComponentName = componentName;
                MissingType = missingType;
                MissingDetail = missingDetail;
            }
        }
        
        private class PrefabMissingInfo
        {
            public readonly string prefabPath;
            public readonly List<MissingComponentInfo> missingComponents;

            public PrefabMissingInfo(string path)
            {
                prefabPath = path;
                missingComponents = new List<MissingComponentInfo>();
            }
        }

        private class PrefabAnimationInfo
        {
            public string prefabPath;
            public List<string> animationNames;
            public PrefabAnimationInfo(string path)
            {
                prefabPath = path;
                animationNames = new List<string>();
            }
        }
        
        private class PrefabTMPInfo
        {
            public string prefabPath;
            public List<string> TMProNames;
            public PrefabTMPInfo(string path)
            {
                prefabPath = path;
                TMProNames = new List<string>();
            }
        }

        [MenuItem("MeEditor/Prefab检查")]
        public static void ShowWindow()
        {
            GetWindow<PrefabDependencyChecker>("Prefab检查器");
        }

        private void OnGUI()
        {
            GUILayout.Label("Prefab检查", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("选择目录:", folderPath);

            if (GUILayout.Button("选择目录", GUILayout.Width(150)))
            {
                string selectedPath = EditorUtility.OpenFolderPanel("选择目录", "Assets", "");
                if (!string.IsNullOrEmpty(selectedPath))
                {
                    folderPath = selectedPath.Replace(Application.dataPath, "Assets");
                }
            }
            EditorGUILayout.EndHorizontal();
            
            if (GUILayout.Button("组件Missing检查"))
            {
                _state = PrefabCheckState.CheckingPrefab;
                CheckPrefabsForMissingReferences();
                _state = PrefabCheckState.CheckingPrefabEnd;
            }
            EditorGUILayout.Space(20);
            
            if (GUILayout.Button("Aniamtion检查"))
            {
                _state = PrefabCheckState.CheckingAniamtion;
                CheckPrefabForAutoAnimation();
                _state = PrefabCheckState.CheckingAniamtionEnd;
            }
            
            EditorGUILayout.Space(20);
            if (GUILayout.Button("ContentSizeFitter检查"))
            {
                _state = PrefabCheckState.CheckingContentSizeFitter;
                CheckPrefabForTMP();
                _state = PrefabCheckState.CheckingContentSizeFitterEnd;
            }
            
            EditorGUILayout.Space(50);
            EditorGUILayout.LabelField("=================检查结果==================");

            if (_state <= PrefabCheckState.CheckingPrefabEnd) {
                if (_prefabsWithMissingReferences.Count > 0)
                {
                    GUILayout.Label($"共检查数量: {totalPrefabsChecked}");
                    GUILayout.Label($"Missing待修复数量: {_prefabsWithMissingReferences.Count}");
                    float scrollViewHeight = position.height - 150;

                    scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(scrollViewHeight));

                    foreach (var prefabInfo in _prefabsWithMissingReferences)
                    {
                        GUIStyle blueButtonStyle = new GUIStyle(GUI.skin.button);
                        blueButtonStyle.normal.textColor = Color.blue;
                        blueButtonStyle.fontSize = 20;
                        blueButtonStyle.alignment = TextAnchor.MiddleLeft;
                        if (GUILayout.Button(prefabInfo.prefabPath, blueButtonStyle, GUILayout.Height(25)))
                        {
                            Selection.activeObject = AssetDatabase.LoadAssetAtPath<GameObject>(prefabInfo.prefabPath);
                            EditorGUIUtility.PingObject(Selection.activeObject);
                        }
                        
                        foreach (var missingComponent in prefabInfo.missingComponents)
                        {
                            EditorGUILayout.BeginHorizontal();
                            GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                            redStyle.normal.textColor = new Color(0.8f, 0.2f, 0.2f, 1);
                            EditorGUILayout.LabelField(missingComponent.ComponentName, redStyle, GUILayout.Width(150));
                            EditorGUILayout.LabelField("组件类型: " + missingComponent.MissingType, GUILayout.Width(150));
                            EditorGUILayout.LabelField("Missing类型: " + missingComponent.MissingDetail);
                            EditorGUILayout.EndHorizontal();
                        }
                        GUILayout.Space(20);
                    }

                    EditorGUILayout.EndScrollView();
                }
                else
                {
                    if (_state == PrefabCheckState.CheckingPrefab)
                    {
                        GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                        redStyle.normal.textColor = Color.red;
                        EditorGUILayout.LabelField("正在检查中，请稍等...", redStyle);
                    }
                    else if (_state == PrefabCheckState.None)
                    {
                        GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                        redStyle.normal.textColor = Color.red;
                        EditorGUILayout.LabelField("请点击执行检查按钮", redStyle);
                    }
                    else
                    {
                        GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                        redStyle.normal.textColor = Color.green;
                        EditorGUILayout.LabelField("恭喜你，全部检查通过！", redStyle);
                    }
                }
            }else if (_state <= PrefabCheckState.CheckingAniamtionEnd)
            {
                if (_prefabAutoAnimationList.Count > 0)
                {
                    GUILayout.Label($"共检查数量: {totalPrefabsChecked}");
                    GUILayout.Label($"带有AutoPlayAnimation的数量: {_prefabAutoAnimationList.Count}");
                    float scrollViewHeight = position.height - 150;

                    scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(scrollViewHeight));

                    foreach (var prefabInfo in _prefabAutoAnimationList)
                    {
                        GUIStyle blueButtonStyle = new GUIStyle(GUI.skin.button);
                        blueButtonStyle.normal.textColor = Color.blue;
                        blueButtonStyle.fontSize = 20;
                        blueButtonStyle.alignment = TextAnchor.MiddleLeft;
                        if (GUILayout.Button(prefabInfo.prefabPath, blueButtonStyle, GUILayout.Height(25)))
                        {
                            Selection.activeObject = AssetDatabase.LoadAssetAtPath<GameObject>(prefabInfo.prefabPath);
                            EditorGUIUtility.PingObject(Selection.activeObject);
                        }
                        
                        foreach (var animName in prefabInfo.animationNames)
                        {
                            EditorGUILayout.BeginHorizontal();
                            GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                            redStyle.normal.textColor = new Color(0.8f, 0.2f, 0.2f, 1);
                            EditorGUILayout.LabelField(animName, redStyle, GUILayout.Width(150));
                            EditorGUILayout.EndHorizontal();
                        }
                        GUILayout.Space(20);
                    }
                    EditorGUILayout.EndScrollView();
                }
                else
                {
                    if (_state == PrefabCheckState.CheckingAniamtion)
                    {
                        GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                        redStyle.normal.textColor = Color.red;
                        EditorGUILayout.LabelField("正在检查中，请稍等...", redStyle);
                    }
                    else
                    {
                        GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                        redStyle.normal.textColor = Color.green;
                        EditorGUILayout.LabelField("恭喜你，全部检查通过！", redStyle);
                    }
                }
            }
            else if (_state <= PrefabCheckState.CheckingContentSizeFitterEnd)
            {
                if (_prefabTMPList.Count > 0)
                {
                    GUILayout.Label($"共检查数量: {totalPrefabsChecked}");
                    GUILayout.Label($"TMP带有无用ContentSizeFitter的数量: {_prefabTMPList.Count}");
                    float scrollViewHeight = position.height - 150;

                    scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(scrollViewHeight));

                    foreach (var prefabInfo in _prefabTMPList)
                    {
                        GUIStyle blueButtonStyle = new GUIStyle(GUI.skin.button);
                        blueButtonStyle.normal.textColor = Color.blue;
                        blueButtonStyle.fontSize = 20;
                        blueButtonStyle.alignment = TextAnchor.MiddleLeft;
                        if (GUILayout.Button(prefabInfo.prefabPath, blueButtonStyle, GUILayout.Height(25)))
                        {
                            Selection.activeObject = AssetDatabase.LoadAssetAtPath<GameObject>(prefabInfo.prefabPath);
                            EditorGUIUtility.PingObject(Selection.activeObject);
                        }
                        
                        foreach (var tmpName in prefabInfo.TMProNames)
                        {
                            EditorGUILayout.BeginHorizontal();
                            GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                            redStyle.normal.textColor = new Color(0.8f, 0.2f, 0.2f, 1);
                            EditorGUILayout.LabelField(tmpName, redStyle, GUILayout.Width(150));
                            EditorGUILayout.EndHorizontal();
                        }
                        GUILayout.Space(20);
                    }
                    EditorGUILayout.EndScrollView();
                }
                else
                {
                    if (_state == PrefabCheckState.CheckingContentSizeFitter)
                    {
                        GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                        redStyle.normal.textColor = Color.red;
                        EditorGUILayout.LabelField("正在检查中，请稍等...", redStyle);
                    }
                    else
                    {
                        GUIStyle redStyle = new GUIStyle(EditorStyles.label);
                        redStyle.normal.textColor = Color.green;
                        EditorGUILayout.LabelField("恭喜你，全部检查通过！", redStyle);
                    }
                }
            } 
        }

    #region Checking Prefabs
        
        /// <summary>
        /// 遍历指定目录下的所有Prefab，检查是否有Missing的引用
        /// </summary>
        private void CheckPrefabsForMissingReferences()
        {
            _prefabsWithMissingReferences.Clear();
            totalPrefabsChecked = 0;
            
            string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab", new[] { folderPath });
            foreach (string guid in prefabGuids)
            {
                string prefabPath = AssetDatabase.GUIDToAssetPath(guid);
                GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);

                if (prefab == null)
                    continue;

                totalPrefabsChecked++;
                PrefabMissingInfo prefabInfo = new PrefabMissingInfo(prefabPath);
                
                if (CheckMissingComponents(prefab, prefabInfo))
                {
                    _prefabsWithMissingReferences.Add(prefabInfo);
                }
            }

            Debug.Log($"Total Prefabs Checked: {totalPrefabsChecked}");
            Debug.Log($"Prefabs with Missing References: {_prefabsWithMissingReferences.Count}");
            foreach (var prefabInfo in _prefabsWithMissingReferences)
            {
                Debug.Log(prefabInfo.prefabPath);
            }
        }
        private bool CheckMissingComponents(GameObject prefab, PrefabMissingInfo prefabInfo)
        {
            bool hasMissingReferences = false;
            
            Component[] components = prefab.GetComponentsInChildren<Component>(true);
            foreach (var component in components)
            {
                if (component == null)
                {
                    prefabInfo.missingComponents.Add(new MissingComponentInfo("Missing Component", "Component", "Component is missing"));
                    hasMissingReferences = true;
                    continue;
                }
                
                SerializedObject so = new SerializedObject(component);
                SerializedProperty prop = so.GetIterator();

                while (prop.NextVisible(true))
                {
                    if (prop.propertyType == SerializedPropertyType.ObjectReference && prop.objectReferenceValue == null && prop.objectReferenceInstanceIDValue != 0)
                    {
                        prefabInfo.missingComponents.Add(new MissingComponentInfo(
                            component.name,
                            component.GetType().Name,
                            prop.displayName
                        ));
                        hasMissingReferences = true;
                    }
                }
            }

            return hasMissingReferences;
        }

    #endregion

    #region Checking Animations
        private void CheckPrefabForAutoAnimation()
        {
            _prefabAutoAnimationList.Clear();
            totalPrefabsChecked = 0;
            string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab", new[] { folderPath });
            foreach (string guid in prefabGuids)
            {
                string prefabPath = AssetDatabase.GUIDToAssetPath(guid);
                GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);

                if (prefab == null)
                    continue;

                totalPrefabsChecked++;
                PrefabAnimationInfo prefabInfo = new PrefabAnimationInfo(prefabPath);
                
                if (CheckAnimationHelper(prefab, prefabInfo))
                {
                    _prefabAutoAnimationList.Add(prefabInfo);
                }
            }

            Debug.Log($"Total Prefabs Checked: {totalPrefabsChecked}");
            Debug.Log($"Prefabs with Missing References: {_prefabAutoAnimationList.Count}");
            foreach (var prefabInfo in _prefabAutoAnimationList)
            {
                Debug.Log(prefabInfo.prefabPath);
            }
        }
        
        private bool CheckAnimationHelper(GameObject prefab, PrefabAnimationInfo prefabInfo)
        {
            bool hasMissingReferences = false;
            
            Animation[] animations = prefab.GetComponentsInChildren<Animation>(true);
            foreach (var anim in animations)
            {
                if (anim.gameObject.GetComponent<Animator>() == null)
                {
                    continue;
                }
                if (anim != null && anim.playAutomatically)
                {
                    prefabInfo.animationNames.Add(anim.name);
                    // 输出 Prefab 名称 和 Animation 名称
                    Debug.Log("======playAutomatically:" + prefabInfo.prefabPath + " " + anim.name);
                    hasMissingReferences = true;
                }
            }

            return hasMissingReferences;
        }
        
    #endregion

    #region Checking ContentSizeFilter

        private void CheckPrefabForTMP()
        {
            _prefabTMPList.Clear();
            totalPrefabsChecked = 0;
            string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab", new[] { folderPath });
            foreach (string guid in prefabGuids)
            {
                string prefabPath = AssetDatabase.GUIDToAssetPath(guid);
                GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
        
                if (prefab == null)
                    continue;
        
                totalPrefabsChecked++;
                PrefabTMPInfo prefabInfo = new PrefabTMPInfo(prefabPath);
                    
                if (CheckTMPHelper(prefab, prefabInfo))
                {
                    _prefabTMPList.Add(prefabInfo);
                }
            }
        
            Debug.Log($"Total Prefabs Checked: {totalPrefabsChecked}");
            Debug.Log($"TextMeshPro with ContentSizeFilter total: {_prefabTMPList.Count}");
            foreach (var prefabInfo in _prefabTMPList)
            {
                Debug.Log(prefabInfo.prefabPath);
            }
        }
            
        private bool CheckTMPHelper(GameObject prefab, PrefabTMPInfo tmpInfo)
        {
            bool checkPass = false;
                
            TextMeshProUGUI[] tmps = prefab.GetComponentsInChildren<TextMeshProUGUI>(true);
            foreach (var tmp in tmps)
            {
                var sizeFitter = tmp.gameObject.GetComponent<ContentSizeFitter>();
                if (sizeFitter == null)
                {
                    continue;
                }
                if (tmp != null && sizeFitter != null &&
                    (sizeFitter.horizontalFit != ContentSizeFitter.FitMode.PreferredSize &&
                    sizeFitter.verticalFit != ContentSizeFitter.FitMode.PreferredSize))
                {
                    tmpInfo.TMProNames.Add(tmp.name);
                    // 输出 Prefab 名称 和 Animation 名称
                    Debug.Log("======TMP with ContentSizeFitter:" + tmpInfo.prefabPath + " " + tmp.name);
                    Debug.Log("======TMP with ContentSizeFitter x:" + sizeFitter.horizontalFit + " ,y:" + sizeFitter.verticalFit);
                    checkPass = true;
                }
            }
        
            return checkPass;
        }
        
    #endregion
    }
}